﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.Contracts;
using System.Linq;

using ProjectBase.Core;
using ProjectBase.Core.Dao;

namespace ProjectBase.Data.Db
{
    /// <summary>
    ///     Holds the IDbRequestSession object.
    ///     Provides the request-living DbCommands for ADO.NET Dao
    /// </summary>
    public static class DbSession
    {
        #region members
        static IDbRequestSession _storage;
        #endregion members

        #region Initialize and Dispose
        public static void Initialize(IDbRequestSession storage)
        {
            _storage = storage;
        }

        public static void Dispose()
        {
            if (_storage.Command.Is())
            {
                if (_storage.Command.Connection.Is())
                {
                    _storage.Command.Connection.Close();
                    _storage.Command.Connection.Dispose();
                }
                _storage.Command.Dispose();
                _storage.Command = null;
            }
        }
        #endregion Initialize and Dispose

        #region singleton
        public static IDbCommand Current
        {
            get
            {
                if (!Global.Settings.EnableDbDao)
                {
                    return null;
                }
                if (_storage.Command.IsNull())
                {
                    _storage.Command = CreateCommand(_storage.OpenTransaction);
                }
                return _storage.Command;
            }
        }

        static IDbCommand CreateCommand(bool openTransaction)
        {
            var command = Global.NewDbCommand();
            try
            {
                command.Connection.Open();
                if (openTransaction)
                {
                    command.Transaction = command.Connection.BeginTransaction();
                }
            }
            catch (Exception ex)
            {
                PublishingManager.Publish(null, "Cannot open Connection to DB", ex);
                command.Connection.Dispose();
                command.Dispose();
                return null;
            }
            return command;
        }
        #endregion singleton

        #region transaction
        /// <summary>
        ///     Provides the access to currently existing transaction property 'IsActive'
        /// </summary>
        public static bool TransactionIsActive
        {
            // Wraper: No need to reference underlying stuff on upper layer
            get
            {
                if (Current.IsNull())
                {
                    return false;
                }
                return _storage.Command.Transaction.Is();
            }
        }

        /// <summary>
        ///     Provides the access to currently existing ISession's "BeginTransaction()";
        /// </summary>
        public static void TransactionBegin()
        {
            // Wraper: No need to reference underlying stuff on upper layer
            if (Current.IsNull())
            {
                return;
            }
            _storage.OpenTransaction = true;
        }

        /// <summary>
        ///     Provides the access to currently existing ISession's "Transaction.Commit()";
        /// </summary>
        public static void TransactionCommit()
        {
            // Wraper: No need to reference underlying stuff on upper layer
            if (Current.IsNull())
            {
                return;
            }
            if (_storage.Command.Transaction.Is()
                &&
                _storage.Command.Connection.Is())
            {
                _storage.Command.Transaction.Commit();
                _storage.Command.Transaction = null;
                Dispose();
                DbCache.Clear();
            }
        }

        /// <summary>
        ///     Provides the access to currently existing ISession's "Transaction.Rollback()";
        /// </summary>
        public static void TransactionRollback()
        {
            // Wraper: No need to reference underlying stuff on upper layer
            if (Current.IsNull())
            {
                return;
            }
            if (_storage.Command.Transaction.Is()
                &&
                _storage.Command.Connection.Is())
            {
                _storage.Command.Transaction.Rollback();
                _storage.Command.Transaction = null;
                Dispose();
            }
        }
        #endregion transaction

        /// <summary>
        ///     Creates new IDbCommand (and clears the old if needed)
        /// </summary>
        public static void Clear()
        {
            // Wraper: No need to reference underlying stuff on upper layer
            if (_storage.Command.IsNull())
            {
                return;
            }
            if (_storage.Command.Is())
            {
                if (_storage.Command.Transaction.Is()
                    &&
                    _storage.Command.Transaction.Connection.Is())
                {
                    _storage.Command.Transaction.Rollback();
                }
                _storage.Command.Connection.Close();
            }
            _storage.Command = null;
        }
    }
}